home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / driverss.zip / WD8003E.ASM < prev    next >
Assembly Source File  |  1991-03-20  |  16KB  |  582 lines

  1. ;History:225,1
  2. version    equ    7
  3.  
  4.     include    defs.asm
  5.  
  6. ;  Russell Nelson, Clarkson University.
  7. ;  Copyright, 1988-1991, Russell Nelson
  8. ;  The following people have contributed to this code: David Horne, Eric
  9. ;  Henderson, Bob Clements, and Jan Engvald LDC.
  10.  
  11. ;   This program is free software; you can redistribute it and/or modify
  12. ;   it under the terms of the GNU General Public License as published by
  13. ;   the Free Software Foundation, version 1.
  14. ;
  15. ;   This program is distributed in the hope that it will be useful,
  16. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. ;   GNU General Public License for more details.
  19. ;
  20. ;   You should have received a copy of the GNU General Public License
  21. ;   along with this program; if not, write to the Free Software
  22. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24. code    segment    byte public
  25.     assume    cs:code, ds:code
  26.  
  27. ; Stuff specific to the Western Digital WD8003E Ethernet controller board
  28. ; C version by Bob Clements, K1BC, May 1988 for the KA9Q TCP/IP package
  29.  
  30. ; The EN registers - First, the board registers
  31.  
  32. EN_CMD        equ    000h    ; Board's command register
  33. EN_REG1        equ    001h    ; 8013 bus size register
  34. EN_REG5        equ    005h    ; New command register (REGISTER 5)
  35. EN_SAPROM    equ    008h    ; Window on station addr prom
  36. EN_REGE        equ    00eh    ; Board Id (code) byte
  37.  
  38. EN_OFF        equ    10h
  39.  
  40. ENDCFG_BM8    equ    48h
  41.  
  42.     include    8390.inc
  43.  
  44. ; Board commands in EN_CMD
  45. EN_RESET    equ    080h    ; Reset the board
  46. EN_MEMEN    equ    040h    ; Enable the shared memory
  47. EN_MEM_MASK    equ    03fh    ; B18-B13 of address of the shared memory
  48.  
  49. ; Bits in REG1
  50. ENR1_BUS16BIT    equ    001h    ; Bus is 16 bits
  51.  
  52. ; Commands for REG5 register
  53. ENR5_MEM16EN    equ    080h    ; Enable 16 bit memory access from bus (8013)
  54. ENR5_LAN16EN    equ    040h    ; Enable 16 bit memory access from chip (8013)
  55. ENR5_MEM_MASK    equ    01fh    ; B23-B19 of address of the memory (8013)
  56. ENR5_LA19    equ    001h    ; B19 of address of the memory (8013)
  57. ENR5_EIL    equ    004h    ; Enable 8390 interrupts to bus (microchannel)
  58.  
  59. ; Bits in the REGE register
  60. ENRE_MICROCHANEL equ    080h    ; Microchannel bus (vs. PC/AT)
  61. ENRE_LARGERAM    equ    040h    ; Large RAM
  62. ENRE_SOFTCONFIG    equ    020h    ; Soft config
  63. ENRE_REVMASK    equ    01eh    ; Revision mask
  64. ENRE_ETHERNET    equ    001h    ; Ethernet (vs. Starlan)
  65.  
  66. ; Shared memory management parameters
  67.  
  68. SM_TSTART_PG    equ    0    ; First page of TX buffer
  69. SM_RSTART_PG    equ    6    ; Starting page of ring
  70. SM_RSTOP_PG    equ    32    ; Last page +1 of ring
  71.  
  72. ; End of WD8003E parameter definitions
  73.  
  74. board_features    db    0    ; Board features
  75. BF_MEM16EN    equ    1    ; 16-bit board, enable 16-bit memory
  76. BF_16K        equ    2    ; Board has 16 KB or shared memory
  77.  
  78. pause_    macro
  79. ;    jmp    $+2
  80. endm
  81.  
  82. ram_enable    macro
  83.     endm
  84.  
  85.  
  86. reset_8390    macro
  87.     loadport        ; First, pulse the board reset
  88.     setport    EN_CMD
  89.     mov    al,EN_RESET        ;Turn on board reset bit
  90.     out    dx,al
  91.     jmp    $+2            ;I guess two are enough.
  92.     jmp    $+2
  93.     xor    al,al            ;Turn off board reset bit
  94.     out    dx,al
  95.     setport    EN_REG5
  96.     mov    al,ENR5_EIL
  97.     test    sys_features,MICROCHANNEL
  98.     jz    reset_no_mc
  99.     out    dx,al            ; enable 8390 interrupts to bus
  100. reset_no_mc:
  101.     endm
  102.  
  103.  
  104. terminate_board    macro
  105.     endm
  106.  
  107. ; The following three values may be overridden from the command line.
  108. ; If they are omitted from the command line, these defaults are used.
  109.  
  110.     public    int_no, io_addr, mem_base
  111. int_no        db    3,0,0,0        ; Interrupt level
  112. io_addr        dw    0280h,0        ; I/O address for card (jumpers)
  113. mem_base    dw    0d000h,0    ; Shared memory addr (software)
  114.  
  115.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  116. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  117. driver_type    db    14        ;from the packet spec
  118. driver_name    db    'WD8003E',0    ;name of the driver.
  119. driver_function    db    2
  120. parameter_list    label    byte
  121.     db    1    ;major rev of packet driver
  122.     db    9    ;minor rev of packet driver
  123.     db    14    ;length of parameter list
  124.     db    EADDR_LEN    ;length of MAC-layer address
  125.     dw    GIANT    ;MTU, including MAC headers
  126.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  127.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  128.     dw    0    ;(# of successive xmits) - 1
  129. int_num    dw    0    ;Interrupt # to hook for post-EOI
  130.             ;processing, 0 == none,
  131.  
  132. is_186        db    0
  133.  
  134.     extrn    sys_features: byte
  135.  
  136. block_output:
  137. ;enter with cx = byte count, ds:si = buffer location, ax = buffer address
  138.     assume    ds:nothing
  139.     mov    es,mem_base        ; Set up ES:DI at the shared RAM
  140.     mov    di,ax            ; ..
  141. ; Can't use movemem which word aligns to the source, but needs to word
  142. ; align to the destination writing to WD8003ET/A. Fortunately works for
  143. ; all cards.
  144.     inc    cx        ; if odd bytes round up.
  145.     and    cx,not 1
  146.     call    rcopy_subr
  147.  
  148.     clc
  149.     ret            ; End of transmit-start routine
  150.  
  151. block_input:
  152. ;enter with cx = byte count, es:di = buffer location, ax = board address.
  153. ; Old version checked size, memory space, queue length here. Now done
  154. ; in higher level code.
  155. ; Set cx to length of this frame.
  156.     assume    ds:nothing,es:nothing
  157.     push    ds
  158.     mov    ds,mem_base        ; ds:si points at first byte to move
  159.     mov    si,ax
  160.  
  161.     cmp    cx,GIANT
  162.     jbe    rcv_size_ok        ; is the size sane? 
  163.     cmp    ch,cl            ; is it starlan bug (dup of low byte)
  164.     jz    rcv_starlan_bug
  165.     mov    cx,1514            ; cap the length
  166.     jmp    rcv_size_ok
  167. rcv_starlan_bug:            ; fix the starlan bug
  168.     mov    ch,ds:[si+EN_RBUF_NXT_PG] ; Page after this frame
  169.     cmp    ch,bl
  170.     ja    rcv_frm_no_wrap
  171.     add    ch,byte ptr cs:sm_rstop_ptr        ; Wrap if needed
  172.     dec    ch
  173. rcv_frm_no_wrap:
  174.     sub    ch,bl
  175.     dec    ch
  176. rcv_size_ok:
  177.  
  178.     add    ax,cx            ; Find the end of this frame.
  179.     cmp    ah,byte ptr cs:sm_rstop_ptr ; Over the top of the ring?
  180.     jb    rcopy_one_piece        ; Go move it
  181.  
  182. rcopy_wrap:
  183. ; Copy in two pieces due to buffer wraparound.
  184.     mov    ah,byte ptr cs:sm_rstop_ptr ; Compute length of first part
  185.     xor    al,al
  186.     sub    ax,si            ;  as all of the pages up to wrap point
  187.     sub    cx,ax            ; Move the rest in second part
  188.     push    cx            ; Save count of second part
  189.     mov    cx,ax            ; Count for first move
  190.     call    rcopy_subr
  191.     mov    si,SM_RSTART_PG*256    ; Offset to start of first receive page
  192.     pop    cx            ; Bytes left to move
  193. rcopy_one_piece:
  194.     call    rcopy_subr
  195.     pop    ds
  196.     ret
  197.  
  198.  
  199. rcopy_subr:
  200.     test    board_features,BF_MEM16EN; Is this a WD8013?
  201.     je    sm_wd8003        ; no, no need to enable 16-bit access.
  202.     loadport            ; Base of device
  203.     setport    EN_REG5            ; Enable 16-bit access
  204.     mov    al,ENR5_MEM16EN+ENR5_LAN16EN+ENR5_LA19
  205.     out    dx,al
  206.     shr    cx,1            ; convert byte count to word count
  207.     rep    movsw            ; Copy packet
  208.     mov    al,ENR5_LAN16EN+ENR5_LA19 ; Disable 16-bit access to WD8013
  209.     out    dx,al
  210.     jmp    short sm_copied
  211. sm_wd8003:
  212.     shr    cx,1            ; convert byte count to word count
  213.     rep    movsw
  214. sm_copied:
  215.     jnc    rcv_wrap_even        ; odd byte left over?
  216.     lodsw                ;   yes, word fetch
  217.     stosb                ;   and byte store
  218. rcv_wrap_even:
  219.     ret
  220.  
  221.  
  222.     include    8390.asm
  223.  
  224.     public    usage_msg
  225. usage_msg    db    "usage: WD8003E [-n] [-d] [-w] <packet_int_no> [-o] <int_level> <io_addr> <mem_base>",CR,LF,'$'
  226.  
  227.     public    copyright_msg
  228. copyright_msg    db    "Packet driver for Western Digital WD8003 E EBT EB ET/A and E/A, version "
  229.         db    '0'+majver,".",'0'+version,".",'0'+dp8390_version,CR,LF
  230.         db    "Portions Copyright 1988, Robert C. Clements, K1BC",CR,LF,'$'
  231.  
  232. cfg_err_msg    db    "WD8003E Configuration failed. Check parameters.",CR,LF,'$'
  233. no_board_msg    label    byte
  234.     db    "WD8003E apparently not present at this memory address.",CR,LF,'$'
  235. bad_cksum_msg    label    byte
  236.     db    "WD8003E address PROM contents are invalid.",CR,LF,'$'
  237. bad_board_msg    label    byte
  238.     db    "Suggested WD8003E memory address is invalid.",CR,LF,'$'
  239. occupied_msg    label    byte
  240.     db    "Suggested WD8003E memory address already occupied.",CR,LF,'$'
  241. using_16bits    db    "Accessing the board using 16 bits of data.",CR,LF,'$'
  242. int_no_name    db    "Interrupt number ",'$'
  243. io_addr_name    db    "I/O port ",'$'
  244. mem_base_name    db    "Memory address ",'$'
  245.  
  246. occupied_switch    db    0        ;if zero, don't use occupied test.
  247.  
  248.     extrn    set_recv_isr: near
  249.     extrn    skip_blanks: near
  250.  
  251. ;enter with si -> argument string, di -> word to store.
  252. ;if there is no number, don't change the number.
  253.     extrn    get_number: near
  254.  
  255. ;enter with dx -> name of word, di -> dword to print.
  256.     extrn    print_number: near
  257.  
  258.     public    parse_args
  259. parse_args:
  260.     call    skip_blanks
  261.     cmp    al,'-'            ;did they specify a switch?
  262.     jne    not_switch
  263.     cmp    byte ptr [si+1],'o'    ;did they specify '-o'?
  264.     je    got_occupied_switch
  265.     stc                ;no, must be an error.
  266.     ret
  267. got_occupied_switch:
  268.     mov    occupied_switch,1
  269.     add    si,2            ;skip past the switch's characters.
  270.     jmp    parse_args        ;go parse more arguments.
  271. not_switch:
  272. ; ** start of code added by Reinhard Strebler Universitaet Karlsruhe 1/10/91
  273.     test    sys_features,MICROCHANNEL
  274.     jnz    do_mc_defaults
  275.     jmp    just_parse_args
  276. do_mc_defaults:
  277.  
  278. ; channel selector resides at io 96h
  279. ; POS register base is at io 100h
  280. ; WD8003E ID is one of 6FC0h, 6FC1h or 6FC2h
  281.  
  282. ; search thro' the slots for a wd8003e card
  283.     mov    cx, 8            ; for all channels(slots)
  284.  
  285. ; channel select value for slots 0,1,2.. is 8,9,A etc
  286. ; start with slot 0, and then 7,6,5,4,3,2,1
  287. get_05:
  288.     mov    ax, cx            ; channel number
  289.     or    ax, 08h         ; reg. select value
  290.     mov    dx, 96h         ; channel select register
  291.     out    dx, al            ; select channel
  292.  
  293. ; read adapter id
  294.     mov    dx, 101h
  295.     in    al, dx            ; adapter id - ms byte
  296.     mov    ah, al
  297.     dec    dx
  298.     in    al, dx            ; adapter id - ls byte
  299.  
  300. ; Check if wd8003e
  301.     cmp    ax, 06FC0h
  302.     je    get_10
  303.     cmp    ax, 06FC1h
  304.     je    get_10
  305.     cmp    ax, 06FC2h
  306.     je    get_10
  307.     loop    get_05
  308.  
  309.     mov    dx,offset no_WD8003E_msg
  310.     mov    etopen_diagn,37
  311.     jmp    error_wrt
  312.  
  313. no_WD8003E_msg:
  314.     db    "WD8003E apparently not found.",CR,LF,'$'
  315.  
  316. int_xlate db    03,04,10,15
  317.  
  318. get_10:
  319. ; found our Adapter
  320.  
  321. ; Get WD8003E I/O Address ( read POS Register 0 )
  322.     xor    ax,ax
  323.     mov    dx,102h
  324.     in    al,dx
  325.     and    al,0FEh
  326.     mov    cl,4
  327.     shl    ax,cl
  328.     mov    io_addr,ax
  329. ; Get WD8003E shared RAM memory address (read POS Register 1 )
  330.     xor    ax,ax
  331.     mov    dx,103h
  332.     in    al,dx
  333.     and    al,0FCh
  334.     xchg    al,ah
  335.     mov    mem_base,ax
  336. ; Get WD8003E IRQ (read POS Register 1 )
  337.     xor    ax,ax
  338.     mov    dx,105h
  339.     in    al,dx
  340.     and    al,003h
  341.     mov    bx,offset int_xlate
  342.     xlat    cs:int_xlate
  343.     mov    int_no,al
  344. ; ** end of code added by Reinhard Strebler Universitaet Karlsruhe 1/10/91
  345.  
  346. just_parse_args:
  347.     mov    di,offset int_no
  348.     call    get_number
  349.     mov    di,offset io_addr
  350.     call    get_number
  351.     mov    di,offset mem_base
  352.     call    get_number
  353.     clc
  354.     ret
  355.  
  356.     extrn    etopen_diagn: byte
  357. addr_not_avail:
  358.     mov    dx,offset occupied_msg
  359.     mov    etopen_diagn,34
  360. bad_cksum:
  361.     mov    dx,offset bad_cksum_msg
  362.     mov    etopen_diagn,37
  363.     jmp    short error_wrt
  364. bad_memory:
  365.     mov    dx,offset bad_board_msg
  366.     mov    etopen_diagn,37
  367. no_memory:
  368.     mov    dx,offset no_board_msg
  369.     mov    etopen_diagn,37
  370. error_wrt:
  371.     mov    ah,9
  372.     int    21h
  373.     stc
  374.     ret
  375.  
  376.  
  377. init_card:
  378. ; Now get the board's physical address from on-board PROM into card_hw_addr
  379.     assume ds:code
  380.  
  381.     test    sys_features,MICROCHANNEL
  382.     jz    etopen_no_mc
  383.     or    board_features,BF_16K
  384.     or    endcfg,ENDCFG_WTS
  385.     loadport
  386.     setport    EN_REG5
  387.     mov    al,ENR5_EIL
  388.     out    dx,al        ; enable 8390 interrupts to bus
  389.     jmp    etopen_have_id
  390. etopen_no_mc:            ; Check for WD8013EBT
  391.     loadport        ; WD8013EBT doesn't have register alaasing
  392.     setport    EN_CMD        ; Register 0 may be aliased to Register 8
  393.     mov bx,    dx
  394.     setport    EN_SAPROM
  395.     mov cx,    EN_SAPROM-EN_CMD ; Check 8 bytes
  396. alias_loop:
  397.     in al,    dx        ; Get one register
  398.     mov ah,    al
  399.     xchg bx, dx        ; Switch to other register
  400.     in al,    dx        ; Get other register
  401.     cmp al,    ah        ; Are they the same?
  402.     jne    not_aliased    ; Nope, not aliased
  403.     inc    bx        ; Increment register pair
  404.     inc    dx
  405.     dec    cx        ; Decrement loop counter
  406.     jne    alias_loop    ; Finished?
  407.     jmp    etopen_have_id    ; Aliased; not WD8013EBT
  408. not_aliased:            ; Not aliased; Check for 16-bit board
  409.     loadport
  410.     setport    EN_REG1        ; Bit 0 must be unmodifiable
  411.     in al,    dx        ; Get register 1
  412.     mov bl,    al        ; Store original value
  413.     xor al,    ENR1_BUS16BIT    ; Flip bit 0
  414.     out dx,    al        ; Write it back
  415.     and al,    ENR1_BUS16BIT    ; Throw other bits away
  416.     mov ah,    al        ; Store bit value
  417.     in al,    dx        ; Read register again
  418.     and al,    ENR1_BUS16BIT    ; Throw other bits away
  419.     cmp al,    ah        ; Was it modified?
  420.     jne    board16bit    ; No; board is a WD8013EBT !
  421.     mov al,    bl        ; Get original value
  422.     out dx,    al        ; Write it back
  423.     jmp    etopen_have_id
  424. board16bit:            ; But is it plugged into a 16-bit slot?
  425.     and al,    ENR1_BUS16BIT    ; Throw other bits away
  426.     je    etopen_have_id    ; Nope; silly board installer!
  427.     mov    dx,offset using_16bits
  428.     mov    ah,9
  429.     int    21h
  430.     or    board_features,BF_MEM16EN+BF_16K
  431.     or    endcfg,ENDCFG_WTS
  432.     loadport
  433.     setport    EN_REG5
  434.     mov    al,ENR5_LAN16EN+ENR5_LA19 ; Write LA19 now, but not MEM16EN
  435.     out    dx,al        ; enable 8390 interrupts to bus
  436.  
  437. etopen_have_id:
  438.  
  439.     loadport            ; base of device
  440.     setport    EN_SAPROM        ; Where the address prom is
  441.     cld                ; make sure string mode is right
  442.     push    cs            ; Point es:di at local copy space
  443.     pop    es
  444.     mov di,    offset curr_hw_addr
  445.     mov cx,    EADDR_LEN        ; Set count for loop
  446.     xor bx,    bx            ; Clear the addr ROM checksum
  447. ini_addr_loop:
  448.     in    al,dx            ; Get a byte of address
  449.     stosb                ; Feed it to caller
  450.     add    bl,al            ; Compute the checksum
  451.     inc    dx            ; Next byte at next I/O port
  452.     loop    ini_addr_loop        ; Loop over six bytes
  453.  
  454.     in al,    dx            ; Get seventh byte
  455.     add bl,    al            ; Add it in
  456.     inc    dx            ; Step to eighth byte
  457.     in al,    dx            ; Get last byte
  458.     add bl,    al            ; Final checksum
  459.     cmp bl, 0ffh            ; Correct?
  460.     je    good_cksum
  461.     jmp    bad_cksum        ; No, board is not happy
  462. good_cksum:
  463.  
  464. ; Check if the shared memory address range is available to us
  465.     mov    bx,mem_base
  466.     cmp    occupied_switch,0    ; did they insist?
  467.     jne    no_lim_chk        ; yes, don't check.
  468.     cmp    bh,080h            ; low limit is 8000
  469.     jae    fr_8000
  470.     jmp    bad_memory
  471. fr_8000:
  472.     cmp    bh,0f0h            ; upper limit is F000
  473.     jb    to_f000
  474.     jmp    bad_memory
  475. to_f000:
  476.     test    bx,01ffh        ; must be on a 8 k boundary
  477.     jz    eightk
  478.     jmp    bad_memory
  479. eightk:
  480. no_lim_chk:
  481.     mov    di,8*1024/16        ; 8 kbyte
  482.     mov    sm_rstop_ptr,32
  483.     test    board_features,BF_16K
  484.     jz    just_8k
  485.     mov    cx,16*1024/16        ; 16 kbytes
  486.     mov    sm_rstop_ptr,64
  487. just_8k:
  488.     cmp    occupied_switch,0    ; did they insist?
  489.     jne    is_avail        ; yes, don't check.
  490.     call    occupied_chk        ; check if address range is available
  491.     jnc    is_avail
  492.     jmp    addr_not_avail        ; we HAVE to have at least 8/16 kbyte
  493. is_avail:
  494.     test    board_features,BF_16K
  495.     jnz    not_32k
  496.     mov    di,32*1024/16        ; may be there is space for 32 kbyte
  497.     call    occupied_chk
  498.     jc    not_32k            ; no, then don't try it later either
  499.     and    bh,7
  500.     jnz    not_32k            ; must be on a 32k boundary
  501.     mov    sm_rstop_ptr,128    ; yes, there is space for a WD8003EBT
  502. not_32k:
  503.  
  504. ; Turn on the shared memory block
  505.     loadport
  506.     setport    EN_CMD        ; Point at board command register
  507.     mov ax,    mem_base    ; Find where shared memory will be mapped
  508.     mov al,    ah        ; Shift to right location
  509.     shr al,    1        ;  in the map control word
  510.     and al,    EN_MEM_MASK    ; Just these bits
  511.     or al,    EN_MEMEN    ; Command to turn on map
  512.     test    sys_features,MICROCHANNEL
  513.     jz    AT_card
  514.     mov    al,EN_MEMEN    ; membase handled different for MC card
  515. AT_card:
  516.     out dx,    al        ; Create that memory
  517.  
  518. ; Find how much memory this card has (without destroying other memory)
  519.     mov    si,ax            ; save bord command value
  520.     mov    es,mem_base
  521.     mov    bl,0FFh            ; first try 32 kbyte (WD8003EBT)
  522.     mov    bh,sm_rstop_ptr        ;   or what is available
  523.     dec    bh
  524. memloop:
  525.     dec    bx            ; use even address
  526.     cli                ; disable interrupts
  527.     mov    cx,es:[bx]        ; save old memory contents
  528.     mov    word ptr es:[bx],05A5Ah    ; put testpattern
  529.     loadport
  530.     setport    EN_CCMD            ; drain the board bus for any
  531.     in    al,dx            ;   capacitive memory
  532.     cmp    word ptr es:[bx],05A5Ah    ; any real memory there?
  533.     jne    not_our_mem        ;   no
  534.     setport    EN_CMD            ;   yes
  535.     mov    ax,si
  536.     and    al,0FFh xor EN_MEMEN
  537.     out    dx,al            ; turn off our memory
  538.     jmp    short $+2
  539.     or    al,EN_MEMEN
  540.     cmp    word ptr es:[bx],05A5Ah    ; was it OUR memory?
  541.     out    dx,al            ; turn on our memory.
  542.     jmp    short $+2
  543.     mov    es:[bx],cx        ; restore the original contents.
  544.     sti
  545.     jne    our_mem            ;   yes, it wasn't there any more
  546. not_our_mem:                ;   no, it was still there
  547.     shr    bx,1            ; test if half as much memory
  548.     cmp    bx,1FFFh        ; down to 8 kbyte
  549.     jae    memloop
  550.     jmp    no_memory        ; no memory at address mem_base
  551. our_mem:                ; it IS our memory!
  552.     inc    bh
  553.     mov    sm_rstop_ptr,bh        ; # of 256 byte ring bufs + 1
  554.     mov    ch,bh
  555.     xor    cl,cl
  556.     mov    ax,mem_base
  557.     call    memory_test        ; check all of that memory
  558.     je    mem_ok
  559.     jmp    no_memory
  560. mem_ok:
  561.     ret
  562.  
  563.     public    print_parameters
  564. print_parameters:
  565.     mov    di,offset int_no
  566.     mov    dx,offset int_no_name
  567.     call    print_number
  568.     mov    di,offset io_addr
  569.     mov    dx,offset io_addr_name
  570.     call    print_number
  571.     mov    di,offset mem_base
  572.     mov    dx,offset mem_base_name
  573.     call    print_number
  574.     ret
  575.  
  576.     include    memtest.asm
  577.     include    occupied.asm
  578.  
  579. code    ends
  580.  
  581.     end
  582.